/**
 * Cs340 Fatboy Mafia Team
 */
package fatboy.hypeerweb;

import java.io.Serializable;

/**
 * This abstract class used to implement the State pattern.
 * 
 * Using this class, nodes can actually change its types on the run
 * 	and execute methods differently based on their state.
 * 
 * Singleton classes should inherit from this class, and implement all the
 * 	abstract methods.
 * 
 * @author Ilya Vinogradov
 * 
 * @domain none
 */
public abstract class NodeState implements Serializable{	
	
	/**
	 * Returns a pointer to either: a childless surface node, or if the
	 *  hypercube is complete, a pointer to the "last node".
	 *    
	 * @param thisNode - the node this method performs operations on
	 * 
	 * @pre starting node (from which the search starts) should exist
	 * @post the SurfaceNode (LastNode in case of a perfect hyper cube)
	 */
	protected abstract Node getSurfaceOrLastNode(Node thisNode);
	
	/**
	 * Checks for a child of the specified node (which is also an EdgeNode).
	 *   This is an inherited method.
	 * 
	 * @param thisNode - the node this method performs operations on
	 * @pre the node (passed as an argument) should exist
	 * @post true, if the node has an EdgeNode child, false otherwise
	 */
	public abstract boolean hasEdgeChild(Node thisNode);
	
	/**
	 * Checks for a parent of the specified node (which is also a
	 * 	 SurfaceNode or InteriorNode).
	 *   This is an inherited method.
	 * 
	 * @param thisNode - the node this method performs operations on
	 * @pre the node (passed as an argument) should exist
	 * @post true, if the node has an SurfaceNode or InteriorNode
	 *   parent, false otherwise
	 */
	public abstract boolean hasParent(Node thisNode);

	/**
	 * Returns the address of the first up or down pointer of the
	 *   node passed to this method.
	 *   
	 * @param thisNode - the node this method performs operations on
	 * @pre the node (passed as an argument) should exist, and should
	 *   have at least one up or down pointer
	 * @post address of the first up pointer or down pointer in its 
	 *   the list of pointers
	 */
	public abstract NodeAddress getFirstUpDownNodeAddress(Node thisNode);
	
	/**
	 * Finds the insertion point for adding new nodes. That is,
	 *   the surface node with the lowest address among childless surface nodes 
	 *   (if the hyper cube in incomplete) or the zero-node (if complete).
	 * 
	 * @param thisNode - the node this method performs operations on
	 * @pre starting node (from which the search starts) should exist
	 * @post the node that will become the parent of the next added node.  
	 */
	abstract Node findInsertionPoint(Node thisNode);
	
	/**
	 * Gets the enumerated type of this state.
	 * 
	 * @pre the node state should be be instantiated
	 * @post the enumerated type
	 */
	abstract NodeType getType();	

	
	/**
	 * Asserts that this node's pointers and parent/child are correct for the node type.  
	 * This should probably only be called once an add or remove call has been fully completed.  
	 * 
	 * @param thisNode the node to be checked
	 * 
	 * @pre true
	 * @post the node state is correct
	 */
	public abstract void assertNodeStateIsCorrect(Node thisNode);
}

